/*
** Konami K053260-based hardware
** smse2k driver by unknownfile
**
** USEFUL MAME SOURCE CODE
** - tmnt.c ( Various Konami hardware )
** - parodius.c ( Parodius )
**
** ABOUT THIS DRIVER
** This runs sound hardware based around the K053260 PCM chip and a Z80. It is designed
** as a test driver although it can be used in the Lua environment.
**
** TYPES OF HARDWARE
** - Parodius. Uses a big ROM (60 KB), no bankswitching.
** - Sunset Riders. Bankswitched.
** - Rollergames. Uses a 32KB rom, and uses a YM3812 instead of the usual YM2151.
**
** GAMES KNOWN TO WORK:
** - Thunder Cross II (1991) [ Parodius ]
**
** BUGS:
** - None in this driver at the moment (Scheduler is causing problems)
*/

#include "smse2kincludes.h"
#include "driverincludes.h"
#include "ParoDrv.h"

int CParoDriver::Load(const char *fn) {
	
	// Open the ROMs up (These are for Thunder Cross II)
	FILE_HANDLE sample_rom = filesystem.OpenFile("073-b04.2d",FSYS_PERMISSION_READ);
	FILE_HANDLE code_rom   = filesystem.OpenFile("073-c01.4f", FSYS_PERMISSION_READ); // Z80 code
	
	if (!code_rom) return 1;

	this->code = new CMemory;
	UINT32 fsize = filesystem.GetFileSize(code_rom);
	code->AllocMemory(fsize);
	filesystem.Read(code_rom, code->GetRawMemory(), fsize);

	this->samples = new CMemory;
	fsize = filesystem.GetFileSize(sample_rom);
	samples->AllocMemory(fsize);
	filesystem.Read(sample_rom, samples->GetRawMemory(), fsize);

	filesystem.CloseFile(code_rom);
	filesystem.CloseFile(sample_rom);
	
	return 0;
}


int CParoDriver::Init(CHardware* hardware) {
	
	this->z80 = CPUFactory("Z80");
	z80->Init(3579545);
	z80->AssignMMU(0,this);

	
	nmitimer = new CTimer(hardware);
	nmitimer->SetTimerCallback(this);
	nmitimer->SetStatus(0); // enable it later

	// we need higher precision for this one
	hardware->ChangeScheduler(ATTOTIME_IN_USEC(10000), ATTOTIME_IN_USEC(50));
	hardware->AddCpu(z80);
	memset(memspace,0,0xffff);
	memcpy(memspace,code->GetRawMemory(),0xf000);

	Msg("Hardware init, starting sound\n");

	ym = SoundDeviceFactory("YM2151");
	ym->Init(hardware->mixer, 3579545);

	konami = SoundDeviceFactory("K053260");
	konami->Init(hardware->mixer, 3579545);
	konami->SetRom(0, samples);


	return 0;
}

void CParoDriver::SetSubsong(int song) {

	konami->Write(0, 0x80);
	konami->Write(1, 0);
	
	z80->Interrupt(0, HOLD_LINE);
}

UINT8 CParoDriver::Read8(UINT64 offset) {
	//Msg("READ %04X\n",offset);
	if (offset == 0xf800 || offset == 0xf810) return ym->Read(0);
	if (offset == 0xf801 || offset == 0xf811) return ym->Read(1);
	if ((offset >= 0xfc00) && (offset <= 0xfc2f)) return konami->Read(offset ^ 0xfc00);

	return memspace[offset & 0xffff];
}

void CParoDriver::Timer_Expired(CTimer* timer) {
	if (timer == nmitimer) {
		z80->Interrupt(1, ASSERT_LINE);
	}
}

void CParoDriver::Write8(UINT64 offset, UINT8 data) {
	//Msg("MMU WRITE %04X %02X\n",offset,data);

	if (offset == 0xfa00) {
		z80->Interrupt(1, ASSERT_LINE);
	//	Msg("*** NMI ENABLE\n");
		z80->Interrupt(1, CLEAR_LINE); // clear ahead of time
		nmitimer->SetLength( ATTOTIME_IN_USEC(50) ); // actually 50 usec
		nmitimer->Reset();
	}
	if (offset == 0xf800 || offset == 0xf810) ym->Write(0,data);
	if (offset == 0xf801 || offset == 0xf811) ym->Write(1,data);
	if ((offset >= 0xfc00) && (offset < 0xfc30)) konami->Write(offset ^ 0xfc00, data);

	memspace[offset & 0xffff] = data;

}

void CParoDriver::FreeUnusedResources() { };
void CParoDriver::Close() { };

DRIVER_DOES_NOT_SUPPORT_FILETYPES(CParoDriver);
DRIVER_FACTORY("parodius","Konami K053260-based hardware (Parodius type)",1,CParoDriver);